﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Web;
using RazorBridge.Helpers;

namespace RazorBridge.Mvc
{
    class FrameworkConfigurationFactory
    {
        #region  "Member Variables"

        private string FrameworkConfigName = "FrameworkConfiguration";

        public static readonly FrameworkConfigurationFactory CurrentInstance = new FrameworkConfigurationFactory();

        private FrameworkConfiguration m_configSection = null;

        #endregion

        #region "Public Variables"

        //public FrameworkConfiguration ConfigSection
        //{
        //    get { return m_configSection; }
        //}

        #endregion

        private FrameworkConfigurationFactory()
        {
            InitializeConfig();
        }

        private void InitializeConfig()
        {
            m_configSection = ConfigurationManager.GetSection(FrameworkConfigName) as FrameworkConfiguration;
        }

        public string GetViewFilePath(string key)
        {
            string filePath = string.Empty;
            string pluginKey = string.Empty;
            if (!string.IsNullOrEmpty(key))
            {
                SplitKey(ref pluginKey, ref key);
                FrameworkConfiguration config = this.m_configSection;
                if (config != null && config.PluginConfigs != null && config.PluginConfigs.Count > 0)
                {
                    PluginElement plugElement = config.PluginConfigs[pluginKey];
                    if (plugElement != null && plugElement.ViewConfigs != null && plugElement.ViewConfigs.Count > 0)
                    {
                        Device deviceType = Device.None;
                        ViewConfigElement viewConfigElement = this.GetViewConfigs(config.DeviceConfigs.DefaultDevice, plugElement, out deviceType);
                        if (viewConfigElement != null)
                        {
                            if (viewConfigElement.PlatformViews != null && viewConfigElement.PlatformViews.Count > 0)
                            {
                                //TODO: Enable support for PlatformType Views
                                Platform platformType = this.GetBrowserPlatform();
                                PlatformViewElement platformViewElement = viewConfigElement.PlatformViews[platformType];
                                if (platformViewElement != null && platformViewElement.Views != null && platformViewElement.Views.Count > 0)
                                {
                                    if (platformViewElement.Views[key] != null)
                                    {
                                        filePath = string.Format(CultureInfo.InvariantCulture, "{0}{1}", Constants.RELATIVE_PATH_WILD_CARD, viewConfigElement.Views[key].Path);
                                    }
                                }
                            }
                            else
                            {
                                if (viewConfigElement != null && viewConfigElement.Views != null && viewConfigElement.Views.Count > 0)
                                {
                                    if (viewConfigElement.Views[key] != null)
                                    {
                                        filePath = string.Format(CultureInfo.InvariantCulture, "{0}{1}", Constants.RELATIVE_PATH_WILD_CARD, viewConfigElement.Views[key].Path);
                                    }
                                }
                            }
                        }
                    }

                }
            }

            return filePath;
        }

        public string GetPartialViewFilePath(string key)
        {
            string filePath = string.Empty;
            string pluginKey = string.Empty;
            if (!string.IsNullOrEmpty(key))
            {
                SplitKey(ref pluginKey, ref key);
                FrameworkConfiguration config = this.m_configSection;
                if (config != null && config.PluginConfigs != null && config.PluginConfigs.Count > 0)
                {
                    PluginElement plugElement = config.PluginConfigs[pluginKey];
                    if (plugElement != null && plugElement.ViewConfigs != null && plugElement.ViewConfigs.Count > 0)
                    {
                        Device deviceType = Device.None;
                        ViewConfigElement viewConfigElement = this.GetViewConfigs(config.DeviceConfigs.DefaultDevice, plugElement, out deviceType);

                        if (viewConfigElement != null)
                        {
                            if (viewConfigElement.PlatformViews != null && viewConfigElement.PlatformViews.Count > 0)
                            {
                                //TODO: Enable support for PlatformType Views
                                Platform platformType = this.GetBrowserPlatform();
                                PlatformViewElement platformViewElement = viewConfigElement.PlatformViews[platformType];
                                if (platformViewElement != null && platformViewElement.PartialViews != null && platformViewElement.PartialViews.Count > 0)
                                {
                                    if (plugElement.IsEmbeddedResource && !string.IsNullOrEmpty(plugElement.Assembly))
                                    {
                                        filePath = string.Format(CultureInfo.InvariantCulture, "{0}{1}{2}{3}{4}", Constants.RELATIVE_PATH_WILD_CARD, Constants.PLUGIN_PATH_WILD_CARD, plugElement.Assembly, Constants.PATH_SEPARATOR, viewConfigElement.PartialViews[key].Path);
                                    }
                                    else
                                    {
                                        filePath = string.Format(CultureInfo.InvariantCulture, "{0}{1}", Constants.RELATIVE_PATH_WILD_CARD, viewConfigElement.PartialViews[key].Path);
                                    }
                                }
                            }
                            else
                            {
                                if (viewConfigElement.PartialViews != null && viewConfigElement.PartialViews.Count > 0)
                                {
                                    if (viewConfigElement.PartialViews[key] != null)
                                    {
                                        if (plugElement.IsEmbeddedResource && !string.IsNullOrEmpty(plugElement.Assembly))
                                        {
                                            filePath = string.Format(CultureInfo.InvariantCulture, "{0}{1}{2}{3}{4}", Constants.RELATIVE_PATH_WILD_CARD, Constants.PLUGIN_PATH_WILD_CARD, plugElement.Assembly, Constants.PATH_SEPARATOR, viewConfigElement.PartialViews[key].Path);
                                        }
                                        else
                                        {
                                            filePath = string.Format(CultureInfo.InvariantCulture, "{0}{1}", Constants.RELATIVE_PATH_WILD_CARD, viewConfigElement.PartialViews[key].Path);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            return filePath;
        }

        private Platform GetBrowserPlatform()
        {
            FrameworkConfiguration frameworkConfig = this.m_configSection;
            Device device = GetDeviceType();
            Platform platform = Platform.None;
            if (device != Device.None)
            {
                DeviceConfigElement deviceConfigElement = frameworkConfig.DeviceConfigs[device];
                if (deviceConfigElement != null)
                {
                    string strUserAgent = HttpContext.Current.Request.UserAgent.ToLower(System.Globalization.CultureInfo.CurrentCulture);
                    foreach (var platformConfig in deviceConfigElement.Platforms)
                    {
                        if (strUserAgent.IndexOf(platformConfig.UserAgent, StringComparison.OrdinalIgnoreCase) != -1)
                        {
                            return platformConfig.PlatformType;
                        }
                    }

                }
            }

            return platform;

        }

        private Device GetDeviceType()
        {
            FrameworkConfiguration frameworkConfig = this.m_configSection;
            Device device = Device.None;
            if (frameworkConfig != null)
            {

                if (frameworkConfig.DeviceConfigs != null && frameworkConfig.DeviceConfigs.Count > 0)
                {
                    string strUserAgent = HttpContext.Current.Request.UserAgent.ToLower(System.Globalization.CultureInfo.CurrentCulture);
                    foreach (DeviceConfigElement DeviceConfig in frameworkConfig.DeviceConfigs)
                    {
                        string[] configUserAgents = DeviceConfig.UserAgent.Split(',');
                        foreach (string userAgent in configUserAgents)
                        {
                            bool isExists = strUserAgent.Contains(userAgent);
                            if (isExists)
                            {
                                return DeviceConfig.DeviceType;
                            }
                        }

                    }
                    device = frameworkConfig.DeviceConfigs.DefaultDevice;
                }
            }
            return device;
        }

        private ViewConfigElement GetViewConfigs(Device defaultDevice, PluginElement plugElement, out Device outputDevice)
        {
            ViewConfigElement viewConfigElement = null;
            if (plugElement.ViewConfigs.Count == 1)
            {
                viewConfigElement = plugElement.ViewConfigs[defaultDevice];
                outputDevice = defaultDevice;
            }
            else
            {
                Device device = this.GetDeviceType();
                viewConfigElement = plugElement.ViewConfigs[device];
                outputDevice = device;
            }
            return viewConfigElement;
        }

        private static void SplitKey(ref string pluginKey, ref string key)
        {
            string[] arr = key.Split(Convert.ToChar(Constants.PATH_SEPARATOR, CultureInfo.InvariantCulture));
            if (arr != null && arr.Length == 2)
            {
                pluginKey = arr[0];
                key = arr[1];
            }
        }
    }
}
